package com.example.query.service.impl;

import com.example.query.dto.QueryCondition;
import com.example.query.dto.QueryRequest;
import com.example.query.dto.QueryResponse;
import com.example.query.service.DynamicQueryService;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.sql.Types;

@Service
public class DynamicQueryServiceImpl implements DynamicQueryService {

    private static final Logger log = LoggerFactory.getLogger(DynamicQueryServiceImpl.class);
    private final JdbcTemplate jdbcTemplate;

    public DynamicQueryServiceImpl(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public QueryResponse query(QueryRequest request) {
        validateRequest(request);
        
        // 为计数查询创建独立的参数列表
        List<Object> countParams = new ArrayList<>();
        String countSql = buildQuery(request, countParams, true);
        log.info("Count SQL: {}, Parameters: {}", countSql, countParams);
        
        // 为数据查询创建独立的参数列表
        List<Object> queryParams = new ArrayList<>();
        String sql = buildQuery(request, queryParams, false);
        log.info("Query SQL: {}, Parameters: {}", sql, queryParams);

        // 执行计数查询
        Long total = jdbcTemplate.queryForObject(countSql, Long.class, countParams.toArray());

        // 执行数据查询
        List<Map<String, Object>> data = jdbcTemplate.queryForList(sql, queryParams.toArray());

        QueryResponse response = new QueryResponse();
        response.setTotal(total);
        response.setPage(request.getPage());
        response.setPageSize(request.getPageSize());
        response.setData(data);

        return response;
    }

    private void validateRequest(QueryRequest request) {
        if (!StringUtils.hasText(request.getTableName())) {
            throw new IllegalArgumentException("Table name is required");
        }
        // 这里可以添加更多的验证逻辑
    }

    private void validateSortDirection(String direction) {
        if (!"ASC".equals(direction) && !"DESC".equals(direction)) {
            throw new IllegalArgumentException("Invalid sort direction: " + direction + ". Only ASC or DESC allowed.");
        }
    }

    private String buildQuery(QueryRequest request, List<Object> params, boolean isCount) {
        StringBuilder sql = new StringBuilder();
        
        if (isCount) {
            sql.append("SELECT COUNT(*) FROM ");
        } else {
            sql.append("SELECT ");
            if (request.getFields() != null && !request.getFields().isEmpty()) {
                sql.append(request.getFields().stream()
                        .map(this::escapeField)
                        .collect(Collectors.joining(", ")));
            } else {
                sql.append("*");
            }
            sql.append(" FROM ");
        }
        
        sql.append(escapeField(request.getTableName()));

        // 添加查询条件
        if (request.getConditions() != null && !request.getConditions().isEmpty()) {
            sql.append(" WHERE ");
            for (int i = 0; i < request.getConditions().size(); i++) {
                if (i > 0) {
                    sql.append(" ").append(request.getConditions().get(i).getLogicalOperator()).append(" ");
                }
                appendCondition(sql, request.getConditions().get(i), params);
            }
        }

        if (!isCount) {
            // 添加排序
            if (request.getSorts() != null && !request.getSorts().isEmpty()) {
                sql.append(" ORDER BY ");
                sql.append(request.getSorts().stream()
                        .map(sort -> {
                            validateSortDirection(sort.getDirection());
                            return escapeField(sort.getField()) + " " + sort.getDirection();
                        })
                        .collect(Collectors.joining(", ")));
            }

            // 添加分页，使用getter方法
            sql.append(" LIMIT ?, ?");
            params.add((request.getPage() - 1) * request.getPageSize());
            params.add(request.getPageSize());
        }

        return sql.toString();
    }

    public void appendCondition(StringBuilder sql, QueryCondition condition, List<Object> params) {
        if (condition.getNestedConditions() != null && !condition.getNestedConditions().isEmpty()) {
            sql.append("("); // 开始嵌套条件
            for (int i = 0; i < condition.getNestedConditions().size(); i++) {
                if (i > 0) {
                    sql.append(" ").append(condition.getLogicalOperator()).append(" ");
                }
                appendCondition(sql, condition.getNestedConditions().get(i), params);
            }
            sql.append(")"); // 结束嵌套条件
        } else {
            // 确保field不为null
            if (condition.getField() == null) {
                throw new IllegalArgumentException("Condition field cannot be null");
            }
            sql.append(escapeField(condition.getField()));
            
            switch (condition.getOperator().toUpperCase()) {
                case "EQ":
                    sql.append(" = ?");
                    params.add(condition.getValue());
                    break;
                case "NE":
                    sql.append(" != ?");
                    params.add(condition.getValue());
                    break;
                case "GT":
                    sql.append(" > ?");
                    params.add(condition.getValue());
                    break;
                case "LT":
                    sql.append(" < ?");
                    params.add(condition.getValue());
                    break;
                case "GE":
                    sql.append(" >= ?");
                    params.add(condition.getValue());
                    break;
                case "LE":
                    sql.append(" <= ?");
                    params.add(condition.getValue());
                    break;
                case "LIKE":
                    sql.append(" LIKE ?");
                    params.add("%" + condition.getValue() + "%");
                    break;
                case "IN":
                    sql.append(" IN (?)");
                    params.add(condition.getValue());
                    break;
                default:
                    throw new IllegalArgumentException("Unsupported operator: " + condition.getOperator());
            }
        }
    }

    public String escapeField(String field) {
        // 简单的SQL注入防护，实际项目中可能需要更复杂的处理
        return "`" + field.replace("`", "``") + "`";
    }

} 